﻿using Autofac;
using EWC.Core.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace EWC.Autofac.DependencyInjection
{
    public static class IocManager
    {
        private static object obj = new object();

        private static ILifetimeScope _container { get; set; }

        /// <summary>
        /// 批量注入扩展，将程序集中符合条件的类自动注入到 Autofac 中
        /// </summary>
        /// <param name="containerBuilder">容器构建器</param>
        /// <param name="assembly">程序集</param>
        public static void BatchAutowired(this ContainerBuilder containerBuilder, Assembly assembly)
        {
         
            if (assembly == null)
            {
                throw new ArgumentNullException(nameof(assembly));
            };

            // 瞬时注入
            containerBuilder
                .RegisterAssemblyTypes(assembly)
                .Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces().Contains(typeof(ITransientDependency)))
                .AsSelf()
                .AsImplementedInterfaces()
                .InstancePerDependency()
                .PropertiesAutowired(new AutowiredPropertySelector());

            // 单例注入
            containerBuilder
                .RegisterAssemblyTypes(assembly)
                .Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces().Contains(typeof(ISingletonDependency)))
                .AsSelf()
                .AsImplementedInterfaces()
                .SingleInstance()
                .PropertiesAutowired(new AutowiredPropertySelector());

            // 生命周期注入
            containerBuilder
                .RegisterAssemblyTypes(assembly)
                .Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces().Contains(typeof(IScopedDependency)))
                .AsSelf()
                .AsImplementedInterfaces()
                .InstancePerLifetimeScope()
                .PropertiesAutowired(new AutowiredPropertySelector());
        }


        public static void InitContainer(ILifetimeScope container)
        {
            //防止过程中方法被调用_container发生改变
            if (_container == null)
            {
                lock (obj)
                {
                    if (_container == null)
                    {
                        _container = container;
                    }
                }
            }
        }

        /// <summary>
        /// 手动获取实例
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T Resolve<T>()
        {
            return _container.Resolve<T>();
        }
    }
}
